#ifndef _APPS_BWM_CMANAGEDCLIENT_H_
#define _APPS_BWM_CMANAGEDCLIENT_H_

#include "cclient.h"
#include "decorations/cmanageddecoration.h"

namespace buola { namespace bwm {

/////////////////////////////////////////////////////////////////////////////////

/// represents a client window


/// it doesn't matter if it is decorated, managed or non-managed, it will always
/// have a CClient representation
/// it is the class which controls all others
/////////////////////////////////////////////////////////////////////////////////

class CManagedClient : public CClient
{
public:
//! \name constructor and destructorcreation
//@{
    CManagedClient(Window pID,const XWindowAttributes &pXAttrs);
    ~CManagedClient();
//@}
    void StartManaging();
    void StopManaging();
    
    const std::wstring &GetVisibleName()    {   return mVisibleName;            }

    void InitGrabs();
    void ReleaseGrabs();

    void CalcVisibleName(bool pNotify);
    void CalcPriority(bool pUpdate);
    img::CPicture CalcIcon(const CSize_d&);


    void CreateDecoration();
    
//! \name size & position
//@{
    void InitGeometry();
    bool ShouldPlaceWindow();
    void PlaceWindow();
    void CheckSize();
    bool SetLogicalSize(const CSize_i&);
    bool SetLogicalPos(const CPoint_i&);
    void IncLogicalSize(CSize_i&);
    void IncLogicalPos(CPoint_i&);
//@}

    
////////////////////////////////
// property general functions
//
    void ReadAllProperties();
    void SetAllProperties();
    void UnsetAllProperties();

    const CRect_i &GetIconGeometry()          {   return mNET.mIconGeometry;  }
    Window GetGroupLeader()     {   return mICCCM.mWMHints.mGroupLeader;      }
    bool WantsFocus()   {   return (mWindowType!=gui::EWindowType::DOCK&&mICCCM.mWMHints.mFlags&gui::x11::icccm::HINT_WANTSFOCUS);}

///////////////////////////////
// window manager operations
//
//Activation
    void GiveFocus();
    bool IsActive()     {   return (gRoot->GetActiveClient()==this);    }
    bool CanBeActivated(bool);
    void Activate();
    void DeActivate();

//Close window
    bool CanClose();
    void Close();

//State&Visibility
    bool IsWithdrawn()      {   return (mWMState==gui::x11::icccm::WMSTATE_WITHDRAWN);       }

    void Show();
    void Withdraw();        //reverted with show
    void Iconify();         //reverted with show
    void Fullscreen(bool pFull=true);
    void Maximize(EState pState=EState::MAXIMIZED);
    void Shade(bool=true);
    void Sticky(bool=true);

    void ToDesktop(unsigned int pDesktop);

    void UpdateState();
    bool ShouldCirculate();
    
/////////////////////////
// dragging the window
//
public:
    void DragStart(const CPoint_d &pPos,gui::EDragState pState,gui::EMouseButton pButton,bool pGrab);
    void DragStep(const CPoint_d &pPos);
    void DragEnd();

////////////////////
// event handlers
//
    void OnMapNotify(bool pWMStarting);
    void OnUnmapNotify(bool pSynthetic);
    void OnDestroyNotify();
    void OnPropertyNotify(XPropertyEvent*);

    void OnButtonDown(const CPoint_d&,gui::EMouseButton pButton,int pMods);
    void OnButtonUp(const CPoint_d&,gui::EMouseButton pButton,int pMods);
    void OnMouseMove(const CPoint_d&);
    void OnConfigureRequest(XConfigureRequestEvent*);
    void OnMapRequest();
    bool OnClientMessage(XClientMessageEvent*);
    void OnResizeAlarm();

    void OnDecorationShowMenu(const CPoint_d &pPoint);
    void OnDecorationButton(CManagedDecoration::EButton pButton);
    void OnDecorationActivate();

private:
    std::wstring mVisibleName;
    gui::x11::icccm::EWMState mWMState;
    CManagedDecoration *mManagedDecoration;
    
///////////////////////
// size and position
//
    CSize_i mLogicalSize;     //size of client in visible, normal state
                            //(doesn't include border)
    CPoint_i mLogicalPos;     //pos of client in visible, normal state
                            //(includes border but not virtual offset)

////////////////////////////////////////
// drag info (for moving or resizing)
//
    struct
    {
        gui::EDragState mState;
        CPoint_d mPos;
        gui::EMouseButton mButton;
        bool mGrab;
        CPoint_d mOriginalPos;
    } mDrag;

    struct
    {
        int mPending;
        CPoint_d mPoint;
        gui::x11::CX11SyncCounter *mCounter;
        int64_t mCounterValue;
        gui::x11::CX11SyncAlarm *mAlarm;
    } mResize;

////////////////
// properties
//
    struct
    {
        gui::x11::icccm::ENetState mState;
        std::wstring mName;
        CRect_i mStrut;
        CRect_i mIconGeometry;
        std::vector<img::CPicture> mIcons;
        gui::PIcon mIcon;
    } mNET;

    struct
    {
        std::wstring mName;
        std::string mClass;
        std::string mClientMachine;

        gui::x11::icccm::CSizeHints mSizeHints;
        gui::x11::icccm::CWMHints mWMHints;

        gui::x11::icccm::EWMProtocols mProtocols;
    } mICCCM;
    
    gui::x11::icccm::CMotifHints mMotif;
};

/*namespace bwm*/ } /*namespace buola*/ }

#endif
